package com.neusoft.elm.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.SortedMap;

import javax.servlet.jsp.jstl.sql.Result;
import javax.servlet.jsp.jstl.sql.ResultSupport;
 

/**
 * 完成数据库访问的基础性操作
 * 
 * @author admin
 *
 */
public class BaseDao {
	// 驱动名称
	private static final String DRIVERNAME = "com.mysql.jdbc.Driver";
	// 不同的mysql数据库 和不同的jdbc URL不完全一致：具体请求，具体解决
	private static final String URL = "jdbc:mysql://localhost:3306/elm?&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC";
	// + "?user=root&password=123456&useUnicode=true&characterEncoding=gbk
	// &autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC&driver=com.mysql.cj.jdbc.Driver
	// ";
	private static final String USERNAME = "root";
	private static final String PASSWORD = "root";

	// 1加载驱动 ---》 实例化com.mysql.jdbc.Driver 的类对象 【对象，实例对象】
	static { // 由jre自动调用；只调用一次
		try {
			Class.forName(DRIVERNAME);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 2 jdbc与数据库建连接
	/**
	 * jdbc与数据库建连接
	 * 
	 * @return Connection 对象
	 * @throws SQLException
	 */
	public static Connection buildConnection() throws SQLException {
		Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
		return connection;
	}

	/**
	 * 实现SQL查询语句
	 * 
	 * @param sql
	 *            ：带有占位符的SQL查询语句
	 * @param args
	 *            ：占位符的匹配参数
	 * @return 离线式数据集
	 */
	public Result getDate(String sql, Object[] args) {
		// 数据库连接对象
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		// 查询结果集，SQL语句 查询结果数据
		ResultSet resultSet = null;
		try {
			connection = buildConnection();
			preparedStatement = connection.prepareStatement(sql);
			// 为占位符赋值
			// 判断sql语句中是否有占位符
			if (args == null || args.length == 0) {
				// .....
			} else {
				for (int index = 0; index < args.length; index++) {
					// JDBC 是从1 开始的 ，数组是从0 开始的
					preparedStatement.setObject(index + 1, args[index]);
				}
			}
			// 在线式： 在从resultSet读取数据的过程中，必须保证 Connection ，
			// PreparedStatement必须是活动装状态
			// 单行式： 每次只能从结果集中取出一条记录
			// resultSet.next()
			// 单向式：从上到下，只执行一次
			resultSet = preparedStatement.executeQuery();
			// 将在线式数据集转换为离线式数据集
			// 实现了一次性把服务器端的数据都读入到java端
			Result result = ResultSupport.toResult(resultSet);
			return result;
		} catch (Exception e) {
			// 处理异常
			System.out.println(e.getMessage());
			System.out.println(sql);
			System.out.println(Arrays.toString(args));
		} finally {
			try {
				resultSet.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				preparedStatement.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return null;
	}

	public static void main(String[] args) {
		String sql = "  SELECT  b.businessAddress,b.businessExplain ,b.businessName , b.deliveryPrice , "
				+ " b.orderTypeId , b.remarks , b.starPrice , b.deliveryPrice  , b.businessId  "
				+ "  FROM business b   ";
		Object[] data = null;
		BaseDao baseDao = new BaseDao();
		Result result = baseDao.getDate(sql, data);
		// 返回记录的总行数
		System.out.println(result.getRowCount());
		// 结果集的列名集合
		String[] strings = result.getColumnNames();
		System.out.println(Arrays.toString(strings));
		SortedMap[] sms = result.getRows();
		for (int index = 0; index < sms.length; index++) {
			SortedMap sm = sms[index];
			Object object = sm.get("businessName");
			System.out.print(object + "|");
			object = sm.get("businessAddress");
			System.out.print(object + "|");
			object = sm.get("businessExplain");
			System.out.print(object + "|");
			object = sm.get("businessId");
			System.out.println(object + "|");
			
		}
	}

	/**
	 * 可以完成所有的增删改SQL语句的执行 SQL语句重点占位符 如何向SQL语句中传递数据 占位符 ：类似于函数中的形参 所有的SQl
	 * 语句中的数据都可以使用 ? 替换，其它的SQL语句部分保持不动 INSERT into emp ( label) VALUES( ? )
	 * 
	 * 
	 * 必须保证 args 和sql中的占位符的一一对应关系
	 * 
	 * @param args
	 * @throws SQLException
	 */
	public static void main3(String[] args) {
		String sql = "  INSERT into   emp ( label ,hiredate , sal , logid , logpwd ) "
				+ "VALUES(    ?   ,   ?   ,    ?   ,  ?   ,   ?   ) "; // s是否存在汉语字符

		Object[] data = { "obj", new Date(), 43.21f, "admin", "123456" };
		BaseDao dao = new BaseDao();
		int i = dao.modify(sql, data);
		System.out.println(i);
	}

	/**
	 * 折行增删改SQL语句，返回影响记录 的行数
	 * 
	 * @param sql
	 *            ：带有占位符的SQL语句
	 * @param args
	 *            ： 与占位符一一匹配的数据
	 * @return
	 */
	public int modify(String sql, Object[] args) {
		// 返回-1 ，查询失败
		int i = -1;
		// 连接对象
		Connection connection = null;
		// 执行SQL语句，并且获得返回结果的对象
		PreparedStatement preparedStatement = null;
		try {
			// 建立连接
			connection = buildConnection();
			// 获得Statement 对象
			preparedStatement = connection.prepareStatement(sql);
			// 为占位符赋值
			// 判断sql语句中是否有占位符
			if (args == null || args.length == 0) {
				// .....
			} else {
				for (int index = 0; index < args.length; index++) {
					// JDBC 是从1 开始的 ，数组是从0 开始的
					preparedStatement.setObject(index + 1, args[index]);
				}
			}
			i = preparedStatement.executeUpdate();
		} catch (SQLException e) {
			// 处理异常
			System.out.println(e.getMessage());
			System.out.println(sql);
			System.out.println(Arrays.toString(args));
		} finally {
			try {
				preparedStatement.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				connection.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return i;
	}

	// 最基本的jdbc应用
	public static void main2(String[] args) throws SQLException {
		String sql = " INSERT into  emp ( label)    VALUES('neuedu') ";
		Connection connection = buildConnection();
		// 向数据库传递SQL语句
		PreparedStatement preparedStatement = connection.prepareStatement(sql);
		// 执行数据库的增删改操作，返回影响记录的行数
		int i = preparedStatement.executeUpdate();
		System.out.println(i);
		preparedStatement.close();
		connection.close();
	}

}
